package gui.geometry;

import gui.NetworkView;
import gui.Paintbrush;
import java.awt.BasicStroke;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Point;
//import java.awt.geom.Line2D;
import java.util.ArrayList;
import model.NetworkConnection;

public class NetworkConnectionDescriptor extends GeometryDescriptor {
	private Point p1, p2;
	static ArrayList<Point> checkedPoints = new ArrayList<Point>();
	
	public NetworkConnectionDescriptor(NetworkConnection object, Point point, FontMetrics fm) {
		super(object, point);
		int [] p1Array = NetworkView.getEndPoint(object.node1, object.side1, fm);
		p1 = new Point(p1Array[0], p1Array[1]);
		int [] p2Array = NetworkView.getEndPoint(object.node2, object.side2, fm);
		p2 = new Point(p2Array[0], p2Array[1]);
	}

	public static GeometryDescriptor contains(Point point, NetworkConnection connection, FontMetrics fm) {
		checkedPoints.clear();
		int [] begin = NetworkView.getEndPoint(connection.node1, connection.side1, fm);
		int [] end = NetworkView.getEndPoint(connection.node2, connection.side2, fm);
		int [] control = connection.getControlPoints((int)Math.sqrt((begin[0] - end[0]) * (begin[0] - end[0]))
				+ (begin[1] - end[1]) * (begin[1] - end[1]));
		
		double tx3, tx2, tx1, tx0, ty3, ty2, ty1, ty0;
		tx3 = -1 * begin[0] + 3 * (begin[0] + control[0]) - 3 * (end[0] + control[2]) + end[0];
		tx2 = 3 * begin[0] - 6 * (begin[0] + control[0]) + 3 * (end[0] + control[2]);
		tx1 = -3 * begin[0] + 3 * (begin[0] + control[0]);
		tx0 = begin[0];
		
		ty3 = -1 * begin[1] + 3 * (begin[1] + control[1]) - 3 * (end[1] + control[3]) + end[1];
		ty2 = 3 * begin[1] - 6 * (begin[1] + control[1]) + 3 * (end[1] + control[3]);
		ty1 = -3 * begin[1] + 3 * (begin[1] + control[1]);
		ty0 = begin[1];

		double closest = 0;
		
		for(double i = 0; i <= 1; i += .005) {
			double x = tx3 * i * i * i + tx2 * i * i + tx1 * i + tx0;
			double y = ty3 * i * i * i + ty2 * i * i + ty1 * i + ty0;
			
			double closeX = tx3 * closest * closest * closest + tx2 * closest * closest + tx1 * closest + tx0;
			double closeY = ty3 * closest * closest * closest + ty2 * closest * closest + ty1 * closest + ty0;
			
			if((x - point.x) * (x - point.x) + (y - point.y) * (y - point.y)
					< (closeX - point.x) * (closeX - point.x) + (closeY - point.y) * (closeY - point.y)) {
				closest = i;
			}
		}
		
		int x = (int)(tx3 * closest * closest * closest + tx2 * closest * closest + tx1 * closest + tx0);
		int y = (int)(ty3 * closest * closest * closest + ty2 * closest * closest + ty1 * closest + ty0);
		
		if((x - point.x) * (x - point.x) + (y - point.y) * (y - point.y) < 25) {
			return new NetworkConnectionDescriptor(connection, new Point(x, y), fm);
		}
		return null;
	}
//	public static GeometryDescriptor contains(Point point, NetworkConnection connection, FontMetrics fm) {
//		int [] p1 = NetworkView.getEndPoint(connection.node1, connection.side1, fm);
//		int [] p2 = NetworkView.getEndPoint(connection.node2, connection.side2, fm);		
//		
//		if(point.x < Math.min(p1[0], p2[0]) - 5 || point.x > Math.max(p1[0], p2[0]) + 5
//				|| point.y < Math.min(p1[1], p2[1]) - 5 || point.y > Math.max(p1[1], p2[1]) + 5) {
//			return null;
//		}
//		
//		double tMin = 0, tMax = 1;
//		while(Math.abs(tMax - tMin) > .01) {
//			double xMax = p1[0] + (p2[0] - p1[0]) * tMax;
//			double yMax = p1[1] + (p2[1] - p1[1]) * tMax;
//			double xMin = p1[0] + (p2[0] - p1[0]) * tMin;
//			double yMin = p1[1] + (p2[1] - p1[1]) * tMin;
//			if((xMin - point.x) * (xMin - point.x) + (yMin - point.y) * (yMin - point.y)
//				< (xMax - point.x) * (xMax - point.x) + (yMax - point.y) * (yMax - point.y)) {
//				tMax = (tMin + tMax) / 2;
//			}
//			else {
//				tMin = (tMin + tMax) / 2;
//			}
//		}
//		
//		int x = (int) (p1[0] + (p2[0] - p1[0]) * tMax);
//		int y = (int) (p1[1] + (p2[1] - p1[1]) * tMax);
//		
//		if((x - point.x) * (x - point.x) + (y - point.y) * (y - point.y) < 25) {
//			return new NetworkConnectionDescriptor(connection, new Point(x, y), fm);
//		}
//		return null;
//	}
	
	@Override
	public void draw(Graphics2D g) {
		g.setStroke(new BasicStroke(2));
		g.setColor(Paintbrush.seaFoam);
		g.drawRect(p1.x - 2, p1.y - 2, 5, 5);
		g.drawRect(p2.x - 2, p2.y - 2, 5, 5);
		g.setStroke(new BasicStroke(1));
	}

	public String toString() {
		NetworkConnection connection = (NetworkConnection) object;
		return connection.node1 + " <--> " + connection.node2 + "\tindex: " + index;
	}
}
